package com.heima.wemedia.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.heima.api.feign.ApArticleFeignClient;
import com.heima.audit.baidu.BaiduImageScan;
import com.heima.audit.baidu.BaiduTextScan;
import com.heima.common.constant.DelayConstants;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmSensitiveService;
import com.heima.wemedia.service.WmUserService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAuditServiceImpl implements WmNewsAuditService {
    @Autowired
    private BaiduImageScan baiduImageScan;
    @Autowired
    private BaiduTextScan baiduTextScan;

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private ApArticleFeignClient articleFeignClient;

    @Override
    @Async("taskExecutor")
    public void auditWmNews(WmNews wmNews, List<String> contentImageList) {
        //准备文章文本数据
        List<String> textList   = this.getText(wmNews);
        String allText=new String();
        for (String s : textList) {
            allText=allText+s;
        }
        //准备文章图片数据
        List<String> allImage = this.getImages(wmNews,contentImageList);

        //2. 百度云文本审核
        ResponseResult responseResult = this.baiduTextScan(wmNews, allText);
        if(responseResult!=null){
            log.error("[文章自动审核]百度云文本审核出现问题（可能不合规或疑似），文章ID：{}",wmNews.getId());
            return ;
        }
//3. 百度云图片审核
        responseResult = this.baiduImageScan(wmNews, allImage);
        if(responseResult!=null){
            log.error("[文章自动审核]百度云图片审核出现问题（可能不合规或疑似），文章ID：{}",wmNews.getId());
            return ;
        }
        //4. 处理APP文章的发布
//4.1 获取系统当前时间和文章发布时间
        long currentTime = DateTime.now().getMillis();
        long publishTime = wmNews.getPublishTime().getTime();
//4.2 发布时间未到，则修改文章状态为自动审核通过（待发布8）
        if(publishTime>currentTime){
            this.updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"文章审核通过，发布时间未到");
            log.info("[文章自动审核]文章审核通过待发布，文章ID：{}",wmNews.getId());
            return ;
        }
//4.3 发布时间用到，则 调用Feign创建或更新APP文章 且 修改文章状态为已发布（9）
        responseResult = this.doArticlePublish(wmNews);
        if(responseResult!=null){
            log.error("[文章自动审核]处理APP文章发布出现问题，文章ID：{}",wmNews.getId());
            return;
        }
        log.info("[文章自动审核]文章审核通过已发布，文章ID：{}",wmNews.getId());
    }
    @Autowired
    private RabbitTemplate rabbitTemplate;

    private void checkTextorImage(Integer i, WmNews wmNews) {
        // 8.判断是否审核通过
        if (i == 1) {
            // 审核通过,
            log.info("审核通过");
            // 9.判断发布时间是否已到
            if (wmNews.getPublishTime().getTime() < System.currentTimeMillis()) {
                // 到了修改wmNews的状态为9，且新增article的fergn接口apArticleFeignClient
                wmNews.setStatus(Short.valueOf("9"));
                wmNews.setReason("审核通过");
            } else {
                // 未到改为8
                wmNews.setStatus(Short.valueOf("8"));
                // 获取当前时间和提交时间的毫秒值
                long submitedTime = wmNews.getPublishTime().getTime();
                long now = new Date().getTime();
                // 获取延时发布的时间毫秒值
                long delayTime = submitedTime - now;

                // 并使用死信队列进行延时发布
                log.info("文章审核通过，未到发布时间，使用死信队列进行延时发布");
                Message message = MessageBuilder.withBody(wmNews.getId().toString().getBytes(StandardCharsets.UTF_8))
                        .setHeader("x-delay",delayTime) //消息延迟投递到队列的时间，单位是毫秒
                        .setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)//普通字符串，必须指定为文本格式
                        .build();
                rabbitTemplate.convertAndSend(DelayConstants.WM_NEWS_DELAY_DIRECT, DelayConstants.WM_NEWS_DELAY_KEY, message);
            }
            Long articleId = saveArticle(wmNews);
            wmNews.setArticleId(articleId);
            boolean res = wmNewsService.updateById(wmNews);
            if (!res) {
                throw new RuntimeException("修改文章状态失败");
            }
        } else if (i == 2) {
            // 审核未通过
            log.info("审核未通过");
            wmNews.setStatus(Short.valueOf("2"));
            wmNews.setReason("审核未通过");
            boolean res = wmNewsService.updateById(wmNews);
            if (!res) {
                throw new RuntimeException("修改文章状态失败");
            }
            throw new RuntimeException("审核未通过");
        } else {
            // 审核存在不确定内容，转人工审核
            wmNews.setStatus(Short.valueOf("3"));
            wmNews.setReason("审核内容存在不确定内容");
            boolean res = wmNewsService.updateById(wmNews);
            if (!res) {
                throw new RuntimeException("修改文章状态失败");
            }
            throw new RuntimeException("审核未通过");
        }
    }

    private  List<String> getText(WmNews wmNews) {
        List<String> contentTextList = new ArrayList<>();
        List<Map> mapList = JSON.parseArray(wmNews.getContent(), Map.class);
        if(mapList!=null && mapList.size()>0){
            for (Map<String,String> map : mapList) {
                String type = map.get("type");
                if("text".equals(type)){
                    String contentText = map.get("value");//内容中的图片地址
                    contentTextList.add(contentText);
                }
            }
        }
        return contentTextList;
    }

    private List<String> getImages(WmNews wmNews,List<String> contentImageList){
        if(StringUtils.isNotBlank(wmNews.getImages())){
            String[] coverImageArr = wmNews.getImages().split(",");
            List<String> coverImageList = Arrays.asList(coverImageArr); //封面图片地址
            contentImageList.addAll(coverImageList);
        }
        List<String> allImage = contentImageList.stream().distinct().collect(Collectors.toList());
        return allImage;
    }

    @Autowired
    private WmSensitiveService wmSensitiveService;
    /**
     * 更新文章
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews,Short status,String reason){
        wmNews.setReason(reason);
        wmNews.setStatus(status);
        wmNewsService.updateById(wmNews);
    }

    /**
     * 发布时间用到，则 调用Feign创建或更新APP文章 且 修改文章状态为已发布（9）
     * @param wmNews
     * @return
     */
    public ResponseResult doArticlePublish(WmNews wmNews){
//4.3.1 调用Feign创建或更新APP文章
        ArticleDto dto = new ArticleDto();
        dto.setId(wmNews.getArticleId());
        dto.setTitle(wmNews.getTitle());
        dto.setChannelId(wmNews.getChannelId());
        dto.setLayout(wmNews.getType());
        dto.setImages(wmNews.getImages());
        dto.setLabels(wmNews.getLabels());
        dto.setPublishTime(wmNews.getPublishTime());
        dto.setContent(wmNews.getContent());
        //查询自媒体用户
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        if(wmUser!=null){
            dto.setAuthorId(wmUser.getApAuthorId().longValue());//作者id
            dto.setAuthorName(wmUser.getName());//作者名
        }
//查询频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel!=null){
            dto.setChannelName(wmChannel.getName());//频道名
        }
//行为数据默认值
        dto.setLikes(0);
        dto.setCollection(0);
        dto.setComment(0);
        dto.setViews(0);
        if(dto.getId()==null){
            dto.setCreatedTime(new Date());//创建时间
        }
        ResponseResult responseResult = articleFeignClient.save(dto);
        if(responseResult.getCode()!=200){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "调用Feign失败");
        }
        long articleId = Long.valueOf(String.valueOf(responseResult.getData()));
//4.3.2 修改文章状态为已发布（9）
        wmNews.setArticleId(articleId);
        this.updateWmNews(wmNews,WmNews.Status.PUBLISHED.getCode(),"审核通过已发布");
        return null;
    }

    @Autowired
    private FileStorageService fileStorageService;
    /**
     * 百度云图片审核
     * @param wmNews
     * @param allImage
     * @return
     */
    private ResponseResult baiduImageScan(WmNews wmNews, List<String> allImage) {
        if(allImage.size()>0){
            for (String url : allImage) {
//下载图片的字节数组
                byte[] bytes = fileStorageService.downLoadFile(url);
                Integer imageType = baiduImageScan.imageScan(bytes);
//如果审核不合规，则更新文章状态为审核失败（2）
                if(imageType==2){
                    this.updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"百度云图片审核不合规");
                    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云图片审核不合规");
                } else if(imageType==3){
                    this.updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"百度云图片审核疑似");
                    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云图片审核疑似");
                }
            }
        }
        return null;
    }

    /**
     * 百度云文本审核
     * @param wmNews
     * @param allText
     * @return
     */
    private ResponseResult baiduTextScan(WmNews wmNews,String allText){
        Integer textType = baiduTextScan.textScan(allText);
//如果审核不合规，则更新文章状态为审核失败（2）
        if(textType==2){
            this.updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"百度云文本审核不合规");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云文本审核不合规");
        } else if(textType==3){
//如果审核疑似，则更细文章状态为待人工审核（3）
            this.updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"百度云文本审核疑似");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云文本审核疑似");
        }
        return null;
    }
}
